package com.lagou.edu.spring.core.defaults;

import com.lagou.edu.spring.core.BeanDefinition;
import com.lagou.edu.spring.core.BeanFactory;
import com.lagou.edu.spring.core.BeanPostProcessor;
import com.lagou.edu.spring.exceptions.MySpringException;

import java.lang.reflect.Method;
import java.util.List;

/**
 * bean初始化器，负责完成bean的前后置
 * 初始化方法，以及早期bean的增强操作
 *
 * @author 大犬
 * @date 2020/4/2
 */
public class BeanInitializer {

    private BeanFactory beanFactory;

    public BeanInitializer(BeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }

    public Object preProcess(String beanName, Object bean) {
        List<BeanPostProcessor> postProcessors = safeGet();
        if (postProcessors == null) {
            return bean;
        }
        for (BeanPostProcessor postProcessor : postProcessors) {
            Object o = postProcessor.preProcess(beanName, bean);
            if (o != null) {
                bean = o;
            }
        }
        return bean;
    }

    public Object afterProcess(String beanName, Object bean) {
        List<BeanPostProcessor> postProcessors = safeGet();
        if (postProcessors == null) {
            return bean;
        }
        for (BeanPostProcessor postProcessor : postProcessors) {
            Object o = postProcessor.afterProcess(beanName, bean);
            if (o != null) {
                bean = o;
            }
        }
        return bean;
    }

    public Object earlyWrapper(String beanName, Object bean) {
        List<BeanPostProcessor> postProcessors = safeGet();
        if (postProcessors == null) {
            return bean;
        }
        for (BeanPostProcessor postProcessor : postProcessors) {
            Object o = postProcessor.earlyWrapper(beanName, bean);
            if (o != null) {
                bean = o;
            }
        }
        return bean;
    }

    public void initBean(Object bean, BeanDefinition beanDefinition) {
        // 调用bean的初始化方法
        List<Method> initMethods = beanDefinition.getInitMethods();
        if (initMethods == null) {
            return;
        }
        for (Method initMethod : initMethods) {
            try {
                initMethod.invoke(bean);
            } catch (Exception e) {
                throw new MySpringException("invoke init method failed", e);
            }
        }
    }

    private List<BeanPostProcessor> safeGet() {
        List<BeanPostProcessor> postProcessors;
        try {
            postProcessors = beanFactory.getBeans(BeanPostProcessor.class);
        } catch (Throwable e) {
            postProcessors = null;
        }
        return postProcessors;
    }

}
